#include "dynamictypemanager.h"

#include "../types/multiset.h"
#include "../types/timedmultiset.h"
#include "../wfnet.h"

#include <typefactory.h>

using namespace wfnet;

DynamicTypeManager* dynamicTypeManager = 0;

DynamicTypeManager* DynamicTypeManager::getInstance()
{
    if (dynamicTypeManager == 0)
    {
        dynamicTypeManager = new DynamicTypeManager();
    }

    return dynamicTypeManager;
}

void DynamicTypeManager::destroy()
{
    delete dynamicTypeManager;
    dynamicTypeManager = 0;
}

void DynamicTypeManager::registerColorSet(const ColorSetName& name,
    const ValueType& type, WfNet* net, bool isTimed)
{
    Q_ASSERT(net != 0);

    CombinedKey key(name, net);

    if (!m_registeredColorSets.contains(key) &&
        TypeFactory::getInstance()->isRegistered(type))
    {
        ColorSet color(name, type, isTimed);

        if (!TypeFactory::getInstance()->isRegistered(color))
        {
            // can happen that user has registered the ColorSet by himself
            TypeFactory::getInstance()->registerType(color);
        }

        Type* multiset = 0;
        TimedMultiset tmt(name);
        Multiset mt(name);

        if (isTimed)
        {
            multiset = &tmt;
        }
        else
        {
            multiset = &mt;
        }

        if (!TypeFactory::getInstance()->isRegistered(*multiset))
        {
            // can happen that user has registered Multiset by himself

            TypeFactory::getInstance()->registerType(*multiset);
        }

        m_registeredColorSets[key] = type.name();

        net->registerColorSet(name);
    }
}

void DynamicTypeManager::registerVariable(const VariableName& name,
    const ColorSetName& type, WfNet* net)
{
    Q_ASSERT(net != 0);

    CombinedKey key(name, net);
    CombinedKey colorSet(type, net);

    if (!m_registeredVariables.contains(key) &&
        m_registeredColorSets.contains(colorSet))
    {
        m_registeredVariables[key] = type;

        net->registerVariable(name);
    }
}

void DynamicTypeManager::unregisterColorSet(const ColorSetName& name,
    WfNet* net)
{
    Q_ASSERT(net != 0);

    CombinedKey key(name, net);

    if (m_registeredColorSets.contains(key))
    {
        const ColorSet* color = getColorSet(name, net);

        Q_ASSERT(color != 0);

        Type* multiset = 0;
        TimedMultiset tmt(name);
        Multiset mt(name);

        if (color->isTimed())
        {
            multiset = &tmt;
        }
        else
        {
            multiset = &mt;
        }

        TypeFactory::getInstance()->unregisterType(multiset->name());

        TypeFactory::getInstance()->unregisterType(name);
        m_registeredColorSets.remove(key);

        net->unregisterColorSet(name);
    }
}

void DynamicTypeManager::unregisterVariable(const VariableName& name,
    WfNet* net)
{
    Q_ASSERT(net != 0);

    CombinedKey key(name, net);

    if (m_registeredVariables.contains(key))
    {
        m_registeredVariables.remove(key);

        net->unregisterVariable(name);
    }
}

const ColorSet* DynamicTypeManager::getColorSet(const ColorSetName& name,
    const WfNet*const net) const
{
    const ColorSet* ret = 0;

    CombinedKey key(name, net);
    if (m_registeredColorSets.contains(key))
    {
        ret = dynamic_cast<const ColorSet*>(
            TypeFactory::getInstance()->getTypeInstance(name));
    }

    return ret;
}

const Type* DynamicTypeManager::getVariable(const VariableName& name,
    const WfNet*const net) const
{
    const Type* variable = 0;

    CombinedKey key(name, net);
    if (m_registeredVariables.contains(key))
    {
        variable = TypeFactory::getInstance()->getTypeInstance(
            m_registeredVariables[key]);
    }

    return variable;
}

DynamicTypeManager::DynamicTypeManager() : m_registeredColorSets(),
    m_registeredVariables()
{

}

DynamicTypeManager::~DynamicTypeManager()
{

}

